package com.ruan.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ruan.entity.LoginUser;
import com.ruan.entity.Orders;
import com.ruan.entity.R;
import com.ruan.entity.User;
import com.ruan.mapper.PermissionsMapper;
import com.ruan.query.UserQuery;
import com.ruan.service.UserService;
import com.ruan.mapper.UserMapper;
import com.ruan.utils.Auth0JwtUtils;
import com.ruan.utils.LongAuth0JwtUtils;
import com.ruan.utils.OssUtil;
import com.ruan.utils.RedisCache;
import com.ruan.vo.UserVo;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.util.HashMap;
import java.util.List;
import java.util.Objects;

/**
* @author 59499
* @description 针对表【user】的数据库操作Service实现
* @createDate 2023-09-07 19:02:30
*/
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User>
    implements UserService{

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private RedisCache redisCache;
    @Autowired
    private UserMapper userMapper;

    @Autowired
    private PermissionsMapper permissionsMapper;

    @Autowired
    private RabbitTemplate rabbitTemplate;
    // 验证码前缀，这个是注册，的以后可能还会有订单
    static final String KEY_PREFIX = "user:code:phone:";
    static final Logger logger = LoggerFactory.getLogger(UserService.class);
    static final String regex = "[1][34578][0-9]{9}";//手机号码的格式：第一位只能为1，第二位可以是3，4，5，7，8，第三位到第十一位可以为0-9中任意一个数字

    @Override
    public R<Void> register(User user) {
        User user1 = userMapper.selectOne(new QueryWrapper<User>().eq("username", user.getUsername()));
        if (user1 != null) {
            return new R<>(100, "该用户名已被注册");
        }
        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        String encodedPassword = passwordEncoder.encode(user.getPassword());
        user.setPassword(encodedPassword);
        int row = userMapper.insert(user);
        int row1 = userMapper.setUserRole(user.getId());
        if (row != 1 || row1 != 1) {
            return new R<>(100, "注册失败");
        } else {
            return new R<>(200, "注册成功");
        }
    }

    @Override
    public R<HashMap<String, String>> login(User user) {
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);
        if (Objects.isNull(authenticate)) {
            return new R<>(100, "用户名或密码错误");
        }
        //使用userid生成token
        LoginUser loginUser = (LoginUser) authenticate.getPrincipal();
        String userId = loginUser.getUser().getId();
        HashMap<String, Object> userMap = new HashMap<>();
        userMap.put("userId", userId);
        String token = Auth0JwtUtils.sign(userMap);
        String longToken = LongAuth0JwtUtils.sign(userMap);
        loginUser.setToken(token);
        loginUser.setLongToken(longToken);
        //authenticate存入redis
        redisCache.setCacheObject("login:" + userId, loginUser);
        //把token响应给前端
        HashMap<String, String> map = new HashMap<>();
        map.put("token", token);
        map.put("id", String.valueOf(loginUser.getUser().getId()));
        map.put("userType", String.valueOf(loginUser.getUser().getUserType()));
        map.put("avatar", loginUser.getUser().getAvatar());
        map.put("userName", loginUser.getUser().getUsername());
        map.put("nickName", loginUser.getUser().getNickname());
        return new R<>(200, "登陆成功", map);
    }

    @Override
    public R<Void> logout() {
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser) authentication.getPrincipal();
        String userid = loginUser.getUser().getId();
        redisCache.deleteObject("login:" + userid);
        return new R<>(200, "退出成功");
    }

    @Override
    public R<HashMap<String, String>> smsLogin(String telephone) {
        User user = userMapper.selectOne(new QueryWrapper<User>().eq("phone_number", telephone));
        List<String> permissionKeyList = permissionsMapper.selectPermsByUserId(user.getId());
        LoginUser loginUser = new LoginUser(user, permissionKeyList);
        String userId = loginUser.getUser().getId();
        HashMap<String, Object> userMap = new HashMap<>();
        userMap.put("userId", userId);
        String token = Auth0JwtUtils.sign(userMap);
        String longToken = LongAuth0JwtUtils.sign(userMap);
        loginUser.setToken(token);
        loginUser.setLongToken(longToken);
        //authenticate存入redis
        redisCache.setCacheObject("login:" + userId, loginUser);
        //把token响应给前端
        HashMap<String, String> map = new HashMap<>();
        map.put("token", token);
        map.put("id", String.valueOf(loginUser.getUser().getId()));
        map.put("userType", String.valueOf(loginUser.getUser().getUserType()));
        map.put("avatar", loginUser.getUser().getAvatar());
        map.put("userName", loginUser.getUser().getUsername());
        map.put("nickName", loginUser.getUser().getNickname());
        return new R<>(200, "登陆成功", map);
    }

    @Override
    public R<String> uploadAvatar(MultipartFile file) {
        //获取上传的文件名
        String fileName = file.getOriginalFilename();
        //产生新的文件名，时间戳+原先文件名后缀
        String newFileName = null;
        if (fileName != null) {
            newFileName = System.currentTimeMillis()+fileName.substring(fileName.lastIndexOf('.'));
        }
        String path = "avatar/";
        String url = null;
        if (newFileName != null) {
            try{
                url = OssUtil.upload(newFileName, file.getInputStream(),path);
            }catch (Exception e){
                return new R<>(100,"上传失败");
            }
        }
        return new R<>(200,"上传成功",url);
    }

    @Override
    public R<User> getUserById(String id) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.select("id","nickname","phone_number","email","sex","age","avatar");
        wrapper.eq("id",id);
        User user = userMapper.selectOne(wrapper);
        return new R<>(200,"查询成功",user);
    }

    @Override
    public R<Void> editUser(UserVo userVo) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("phone_number",userVo.getPhoneNumber());
        User user1 = userMapper.selectOne(wrapper);
        if (user1 != null){
            if (!user1.getId().equals(userVo.getId())){
                return new R<>(100,"该手机号已存在");
            }
        }

        User user = userMapper.selectById(userVo.getId());
        user.setNickname(userVo.getNickname());
        user.setAvatar(userVo.getAvatar());
        user.setPhoneNumber(userVo.getPhoneNumber());
        user.setSex(userVo.getSex());
        user.setAge(userVo.getAge());
        user.setEmail(userVo.getEmail());
        int row = userMapper.updateById(user);
        if (row != 1){
            return new R<>(100,"修改失败");
        }
        return new R<>(200,"修改成功");
    }

    @Override
    public R<IPage<User>> getUserList(UserQuery userQuery) {
        QueryWrapper<User> wrapper = new QueryWrapper<>();
        wrapper.eq("status",1);
        wrapper.eq("user_type",2);
        if (userQuery.getId()!=null && !Objects.equals(userQuery.getId(), "")){
            wrapper.eq("id",userQuery.getId());
        }
        Page<User> userPage = new Page<>(userQuery.getPageNum(),userQuery.getPageSize());
        IPage<User> userIPage = userMapper.selectPage(userPage,wrapper);
        return new R<>(200,"查询成功",userIPage);
    }
}




